namespace XEAS.Framework.Security
{
    using System;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Security.Cryptography;
    using System.Text;

    public class FileEncryptor : IDisposable
    {
        public event CryptoCompletedEventHandler CryptoCompletedEvent;

        public event CryptoProgressEventHandler CryptoProgressEvent;

        public void DecryptFile(string inFile, string outFile, string password)
        {
            this.DecryptFile(inFile, outFile, password, 0);
        }

        public void DecryptFile(string inFile, string outFile, string password, int bufferSize)
        {
            SymmetricAlgorithm algorithm = null;
            FileStream stream;
            long num = 0L;
            byte[] buffer = new byte[0x100];
            if (bufferSize == 0)
            {
                bufferSize = 0x100;
            }
            if ((inFile == null) || (inFile == ""))
            {
                throw new Exception("'inFile' cannot be null.");
            }
            if ((outFile == null) || (outFile == ""))
            {
                throw new Exception("'outFile' cannot be null.");
            }
            if ((password == null) || (password == ""))
            {
                throw new Exception("'password' cannot be null.");
            }
            FileStream stream2 = new FileStream(inFile, FileMode.Open, FileAccess.Read, FileShare.None, (bufferSize * 0x400) - 1);
            try
            {
                stream = new FileStream(outFile, FileMode.Create, FileAccess.Write, FileShare.None, (bufferSize * 0x400) - 1);
            }
            catch (Exception exception)
            {
                stream2.Close();
                throw exception;
            }
            byte[] buffer2 = new byte[((bufferSize * 0x400) - 1) + 1];
            FileEncryptorEventArgs e = new FileEncryptorEventArgs();
            e.StartTimeInternal = DateTime.Now;
            long length = stream2.Length;
            e.BytesTotalInternal = length;
            num += stream2.Read(buffer, 0, buffer.Length);
            string str = Encoding.ASCII.GetString(buffer);
            switch (str.Substring(str.Length - 2))
            {
                case "01":
                    algorithm = new DESCryptoServiceProvider();
                    break;

                case "02":
                    algorithm = new RC2CryptoServiceProvider();
                    break;

                case "03":
                    algorithm = new TripleDESCryptoServiceProvider();
                    break;

                case "04":
                    algorithm = new RijndaelManaged();
                    break;
            }
            byte[] destinationArray = new byte[((algorithm.LegalKeySizes[0].MaxSize / 8) - 1) + 1];
            algorithm.BlockSize = algorithm.LegalBlockSizes[0].MaxSize;
            byte[] sourceArray = this.HashStringToByteArray(password);
            Array.Copy(sourceArray, destinationArray, destinationArray.Length);
            algorithm.Key = destinationArray;
            algorithm.IV = Convert.FromBase64String(str.Substring(0x7f, 0x7f).Trim());
            if (!(str.Substring(0, 0x7f).Trim() == this.HashStringToBase64String(Convert.ToBase64String(sourceArray) + Convert.ToBase64String(algorithm.IV))))
            {
                stream2.Close();
                stream.Close();
                e.Dispose();
                algorithm.Clear();
                throw new Exception("The password specified is invalid.");
            }
            CryptoStream stream3 = new CryptoStream(stream, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
            while (num < length)
            {
                int count = stream2.Read(buffer2, 0, buffer2.Length);
                num += count;
                e.BytesDoneInternal = num;
                stream3.Write(buffer2, 0, count);
                e.EndTimeInternal = DateTime.Now;
                if (this.CryptoProgressEvent != null)
                {
                    this.CryptoProgressEvent(this, e);
                }
                if (e.Cancel)
                {
                    break;
                }
            }
            stream3.FlushFinalBlock();
            stream3.Close();
            stream3.Clear();
            stream.Close();
            stream2.Close();
            algorithm.Clear();
            e.EndTimeInternal = DateTime.Now;
            if (this.CryptoCompletedEvent != null)
            {
                this.CryptoCompletedEvent(this, e);
            }
            e.Dispose();
        }

        public string DecryptStringFromBase64String(string value, string password)
        {
            SymmetricAlgorithm algorithm = null;
            if ((value == null) || (value == ""))
            {
                throw new Exception("'value' cannot be null.");
            }
            if ((password == null) || (password == ""))
            {
                throw new Exception("'password' cannot be null.");
            }
            switch (value.Substring(0xfe, 2))
            {
                case "01":
                    algorithm = new DESCryptoServiceProvider();
                    break;

                case "02":
                    algorithm = new RC2CryptoServiceProvider();
                    break;

                case "03":
                    algorithm = new TripleDESCryptoServiceProvider();
                    break;

                case "04":
                    algorithm = new RijndaelManaged();
                    break;
            }
            byte[] destinationArray = new byte[((algorithm.LegalKeySizes[0].MaxSize / 8) - 1) + 1];
            algorithm.BlockSize = algorithm.LegalBlockSizes[0].MaxSize;
            byte[] sourceArray = this.HashStringToByteArray(password);
            Array.Copy(sourceArray, destinationArray, destinationArray.Length);
            algorithm.Key = destinationArray;
            algorithm.IV = Convert.FromBase64String(value.Substring(0x7f, 0x7f).Trim());
            if (!(value.Substring(0, 0x7f).Trim() == this.HashStringToBase64String(Convert.ToBase64String(sourceArray) + Convert.ToBase64String(algorithm.IV))))
            {
                algorithm.Clear();
                throw new Exception("The password specified is invalid.");
            }
            MemoryStream stream = new MemoryStream();
            stream.SetLength(0L);
            CryptoStream stream2 = new CryptoStream(stream, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
            stream2.Write(Convert.FromBase64String(value.Substring(0x100)), 0, Convert.FromBase64String(value.Substring(0x100)).Length);
            stream2.FlushFinalBlock();
            string str2 = Encoding.ASCII.GetString(stream.ToArray());
            stream.Close();
            stream2.Clear();
            algorithm.Clear();
            return str2;
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }

        public void EncryptFile(string inFile, string outFile, string password)
        {
            this.EncryptFile(inFile, outFile, password, new RC2CryptoServiceProvider(), 0);
        }

        public void EncryptFile(string inFile, string outFile, string password, SymmetricAlgorithm provider)
        {
            this.EncryptFile(inFile, outFile, password, provider, 0);
        }

        public void EncryptFile(string inFile, string outFile, string password, SymmetricAlgorithm provider, int bufferSize)
        {
            FileStream stream;
            long num = 0L;
            if (bufferSize == 0)
            {
                bufferSize = 0x100;
            }
            if ((inFile == null) || (inFile == ""))
            {
                throw new Exception("'inFile' cannot be null.");
            }
            if ((outFile == null) || (outFile == ""))
            {
                throw new Exception("'outFile' cannot be null.");
            }
            if ((password == null) || (password == ""))
            {
                throw new Exception("'password' cannot be null.");
            }
            FileStream stream2 = new FileStream(inFile, FileMode.Open, FileAccess.Read, FileShare.None, (bufferSize * 0x400) - 1);
            try
            {
                stream = new FileStream(outFile, FileMode.Create, FileAccess.Write, FileShare.None, (bufferSize * 0x400) - 1);
            }
            catch (Exception exception)
            {
                stream2.Close();
                throw exception;
            }
            if (provider == null)
            {
                provider = new RijndaelManaged();
            }
            byte[] destinationArray = new byte[((provider.LegalKeySizes[0].MaxSize / 8) - 1) + 1];
            byte[] buffer = new byte[((bufferSize * 0x400) - 1) + 1];
            FileEncryptorEventArgs e = new FileEncryptorEventArgs();
            e.StartTimeInternal = DateTime.Now;
            provider.BlockSize = provider.LegalBlockSizes[0].MaxSize;
            byte[] sourceArray = this.HashStringToByteArray(password);
            Array.Copy(sourceArray, destinationArray, destinationArray.Length);
            provider.Key = destinationArray;
            provider.GenerateIV();
            string s = this.HashStringToBase64String(Convert.ToBase64String(sourceArray) + Convert.ToBase64String(provider.IV)).PadRight(0x7f) + Convert.ToBase64String(provider.IV).PadRight(0x7f);
            if (provider is DESCryptoServiceProvider)
            {
                s = s + "01";
            }
            else if (provider is RC2CryptoServiceProvider)
            {
                s = s + "02";
            }
            else if (provider is TripleDESCryptoServiceProvider)
            {
                s = s + "03";
            }
            else if (provider is RijndaelManaged)
            {
                s = s + "04";
            }
            long length = stream2.Length;
            e.BytesTotalInternal = length;
            stream.Write(Encoding.ASCII.GetBytes(s), 0, s.Length);
            CryptoStream stream3 = new CryptoStream(stream, provider.CreateEncryptor(), CryptoStreamMode.Write);
            while (num < length)
            {
                int count = stream2.Read(buffer, 0, buffer.Length);
                num += count;
                e.BytesDoneInternal = num;
                stream3.Write(buffer, 0, count);
                e.EndTimeInternal = DateTime.Now;
                if (this.CryptoProgressEvent != null)
                {
                    this.CryptoProgressEvent(this, e);
                }
                if (e.Cancel)
                {
                    break;
                }
            }
            stream3.FlushFinalBlock();
            stream3.Close();
            stream3.Clear();
            stream.Close();
            stream2.Close();
            provider.Clear();
            e.EndTimeInternal = DateTime.Now;
            if (this.CryptoCompletedEvent != null)
            {
                this.CryptoCompletedEvent(this, e);
            }
            e.Dispose();
        }

        public string EncryptStringToBase64String(string value, string password)
        {
            return this.EncryptStringToBase64String(value, password, null);
        }

        public string EncryptStringToBase64String(string value, string password, SymmetricAlgorithm provider)
        {
            if ((value == null) || (value == ""))
            {
                throw new Exception("'value' cannot be null.");
            }
            if ((password == null) || (password == ""))
            {
                throw new Exception("'password' cannot be null.");
            }
            if (provider == null)
            {
                provider = new RijndaelManaged();
            }
            byte[] destinationArray = new byte[((provider.LegalKeySizes[0].MaxSize / 8) - 1) + 1];
            provider.BlockSize = provider.LegalBlockSizes[0].MaxSize;
            byte[] sourceArray = this.HashStringToByteArray(password);
            Array.Copy(sourceArray, destinationArray, destinationArray.Length);
            provider.Key = destinationArray;
            provider.GenerateIV();
            string str = this.HashStringToBase64String(Convert.ToBase64String(sourceArray) + Convert.ToBase64String(provider.IV)).PadRight(0x7f) + Convert.ToBase64String(provider.IV).PadRight(0x7f);
            if (provider is DESCryptoServiceProvider)
            {
                str = str + "01";
            }
            else if (provider is RC2CryptoServiceProvider)
            {
                str = str + "02";
            }
            else if (provider is TripleDESCryptoServiceProvider)
            {
                str = str + "03";
            }
            else if (provider is RijndaelManaged)
            {
                str = str + "04";
            }
            MemoryStream stream = new MemoryStream();
            stream.SetLength(0L);
            CryptoStream stream2 = new CryptoStream(stream, provider.CreateEncryptor(), CryptoStreamMode.Write);
            stream2.Write(Encoding.ASCII.GetBytes(value), 0, Encoding.ASCII.GetBytes(value).Length);
            stream2.FlushFinalBlock();
            string str2 = str + Convert.ToBase64String(stream.ToArray());
            stream.Close();
            stream2.Clear();
            provider.Clear();
            return str2;
        }

        ~FileEncryptor()
        {
            this.Dispose(false);
        }

        public string HashFileToBase64String(string file)
        {
            return this.HashFileToBase64String(file, null, 0);
        }

        public string HashFileToBase64String(string file, HashAlgorithm provider)
        {
            return this.HashFileToBase64String(file, provider, 0);
        }

        public string HashFileToBase64String(string file, HashAlgorithm provider, int bufferSize)
        {
            string str = string.Empty;
            long num = 0L;
            if (bufferSize == 0)
            {
                bufferSize = 0x100;
            }
            if ((file == null) || (file == ""))
            {
                throw new Exception("'file' cannot be null.");
            }
            FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None, (bufferSize * 0x400) - 1);
            if (provider == null)
            {
                provider = new SHA512Managed();
            }
            byte[] buffer = new byte[((bufferSize * 0x400) - 1) + 1];
            byte[] outputBuffer = new byte[((bufferSize * 0x400) - 1) + 1];
            FileEncryptorEventArgs e = new FileEncryptorEventArgs();
            e.StartTimeInternal = DateTime.Now;
            long length = stream.Length;
            e.BytesTotalInternal = length;
            while (num < length)
            {
                int inputCount = stream.Read(buffer, 0, buffer.Length);
                num += inputCount;
                e.BytesDoneInternal = num;
                if (num != length)
                {
                    provider.TransformBlock(buffer, 0, inputCount, outputBuffer, 0);
                }
                else
                {
                    provider.TransformFinalBlock(buffer, 0, inputCount);
                }
                e.EndTimeInternal = DateTime.Now;
                if (this.CryptoProgressEvent != null)
                {
                    this.CryptoProgressEvent(this, e);
                }
                if (e.Cancel)
                {
                    break;
                }
            }
            stream.Close();
            if (!e.Cancel)
            {
                str = Convert.ToBase64String(provider.Hash);
            }
            provider.Clear();
            e.EndTimeInternal = DateTime.Now;
            if (this.CryptoCompletedEvent != null)
            {
                this.CryptoCompletedEvent(this, e);
            }
            e.Dispose();
            return str;
        }

        public string HashStringToBase64String(string value)
        {
            return this.HashStringToBase64String(value, null);
        }

        public string HashStringToBase64String(string value, HashAlgorithm provider)
        {
            if ((value == null) || (value == ""))
            {
                throw new Exception("'value' cannot be null.");
            }
            if (provider == null)
            {
                provider = new SHA512Managed();
            }
            byte[] bytes = Encoding.ASCII.GetBytes(value);
            bytes = provider.ComputeHash(bytes);
            provider.Clear();
            return Convert.ToBase64String(bytes);
        }

        public byte[] HashStringToByteArray(string value)
        {
            return this.HashStringToByteArray(value, null);
        }

        public byte[] HashStringToByteArray(string value, HashAlgorithm provider)
        {
            if ((value == null) || (value == ""))
            {
                throw new Exception("'value' cannot be null.");
            }
            if (provider == null)
            {
                provider = new SHA512Managed();
            }
            byte[] bytes = Encoding.ASCII.GetBytes(value);
            bytes = provider.ComputeHash(bytes);
            provider.Clear();
            return bytes;
        }

        public void OverwriteFile(string file)
        {
            this.OverwriteFile(file, 0, true);
        }

        public void OverwriteFile(string file, bool deleteFile)
        {
            this.OverwriteFile(file, 0, deleteFile);
        }

        public void OverwriteFile(string file, int bufferSize)
        {
            this.OverwriteFile(file, bufferSize, true);
        }

        public void OverwriteFile(string file, int bufferSize, bool deleteFile)
        {
            FileStream stream;
            long num = 0L;
            Files files = null;
            if (bufferSize == 0)
            {
                bufferSize = 0x100;
            }
            if ((file == null) || (file == ""))
            {
                throw new Exception("'file' cannot be null.");
            }
            if (deleteFile)
            {
                files = new Files();
                stream = files.OpenFileForSecureOverwrite(file);
            }
            else
            {
                stream = new FileStream(file, FileMode.Open, FileAccess.Write, FileShare.None, bufferSize);
            }
            if (stream == null)
            {
                throw new IOException("The file could not be opened for overwriting.");
            }
            RandomNumberGenerator generator = RandomNumberGenerator.Create();
            byte[] data = new byte[((bufferSize * 0x400) - 1) + 1];
            FileEncryptorEventArgs e = new FileEncryptorEventArgs();
            e.StartTimeInternal = DateTime.Now;
            long length = stream.Length;
            e.BytesTotalInternal = length;
            while (num < length)
            {
                if ((length - num) < data.Length)
                {
                    data = new byte[Convert.ToInt32((long) ((length - num) - 1L)) + 1];
                }
                generator.GetBytes(data);
                stream.Write(data, 0, data.Length);
                num += data.Length;
                e.BytesDoneInternal = num;
                e.EndTimeInternal = DateTime.Now;
                if (this.CryptoProgressEvent != null)
                {
                    this.CryptoProgressEvent(this, e);
                }
                if (e.Cancel)
                {
                    break;
                }
            }
            stream.Close();
            if (files != null)
            {
                files.Dispose();
            }
            if (!(!deleteFile || e.Cancel))
            {
                File.Delete(file);
            }
            e.EndTimeInternal = DateTime.Now;
            if (this.CryptoCompletedEvent != null)
            {
                this.CryptoCompletedEvent(this, e);
            }
            e.Dispose();
        }

        public delegate void CryptoCompletedEventHandler(object sender, FileEncryptorEventArgs e);

        public delegate void CryptoProgressEventHandler(object sender, FileEncryptorEventArgs e);
    }
}

